package com.kitty.game.fight.item;

import com.kitty.game.equip.message.RespFlyInfo;
import com.kitty.game.role.model.Role;
import com.kitty.game.equip.model.RoleEquip;
import com.kitty.game.fight.bean.Fight;
import com.kitty.game.fight.bean.FightObject;
import com.kitty.game.config.Medicine;
import com.kitty.common.utils.SpringUtils;
import com.kitty.common.utils.Pair;
import com.kitty.game.attribute.AttrService;
import com.kitty.game.enter.FiedValue;
import com.kitty.game.enter.RespNotifyMisc;
import com.kitty.game.fight.message.RespSyncMessage;
import com.kitty.game.fight.service.FightMessageService;
import com.kitty.game.fight.util.FightMessageUtil;
import com.kitty.game.shop.ShopDataPool;
import com.kitty.game.utils.AsktaoUtil;
import com.kitty.game.utils.NumberUtil;
import com.kitty.game.utils.StatusConst;
import com.kitty.mina.Modules;
import com.kitty.mina.message.MessagePusher;
import org.apache.mina.core.session.IoSession;

import java.util.HashMap;
import java.util.Map;
import java.util.ArrayList;
import java.util.List;

public abstract class FightItemHandler {

    private static Map<String, FightItemHandler> handlers = new HashMap<>();


    public void use(Fight fight, FightObject attacker, RoleEquip item) {
        if (!checkCondition(fight, attacker, item)) {
            return;
        }
        Object result = doAction(fight, attacker, item);

        attacker.getRole().save();

        broadcast(fight, attacker, item, result);
    }

    abstract Object doAction(Fight fight, FightObject attacker, RoleEquip item);

    boolean checkCondition(Fight fight, FightObject attacker, RoleEquip item) {
        return true;
    }

    abstract void broadcast(Fight fight, FightObject attacker, RoleEquip item, Object params);

    void notify(Role role, String msg) {
        RespNotifyMisc respNotifyMisc = new RespNotifyMisc();
        respNotifyMisc.setMsg(msg);
        byte[] body = AsktaoUtil.getMessageBody(respNotifyMisc);
        RespSyncMessage respSyncMessage = new RespSyncMessage();
        respSyncMessage.setCode((short) Modules.MSG_NOTIFY_MISC);
        respSyncMessage.setMsg(body);
        MessagePusher.pushMessage(role, respSyncMessage);
    }

    void onAddLife(Fight fight, FightObject attacker, FightObject target, int life) {
        FightMessageService fightMessageService = SpringUtils.getFightMessageService();
        FightMessageUtil.sendFightPackage(fight, fightMessageService.useItem(attacker.getId(), target.getId(), 1002));
        FightMessageUtil.sendFightPackage(fight, fightMessageService.decreaseLife(attacker.getId(), target.getId(), life, 0, 0));
        if (target.isFallDown()) {// 如果目标死亡 并且 使用道具 或者加血技能就复活
            FightMessageUtil.sendFightPackage(fight, fightMessageService.revive(target.getId()));
        }
        target.setCurrLife(target.getCurrLife() + life);// 加上道具所加的气血
        FightMessageUtil.sendFightPackage(fight, fightMessageService.updateTargetLife(target.getId(), target.getCurrLife()));
    }

    void onAddMana(Fight fight, FightObject attacker, FightObject target, int mana) {
        FightMessageService fightMessageService = SpringUtils.getFightMessageService();
        FightMessageUtil.sendFightPackage(fight, fightMessageService.useItem(attacker.getId(), target.getId(), 1003));
        FightMessageUtil.sendFightPackage(fight, fightMessageService.decreaseLife(attacker.getId(), target.getId(), mana, 1, 0));
        FightMessageUtil.sendFightPackage(fight, fightMessageService.updateTargetMana(target.getId(), target.getCurrMana()));
    }

    public static FightItemHandler queryHandler(String name) {
        if (handlers.size() == 0) {
            synchronized (FightItemHandler.class) {
                if (handlers.size() == 0) {
                    init();
                }
            }
        }

        FightItemHandler handler = handlers.get(name);
        if (handler == null) {
            Medicine medicine = ShopDataPool.getMedicineBy(name);
            if (medicine != null) {
                handler = handlers.get("普通药品");
            }
        }
        return handler;
    }

    private static void init() {
        handlers.put("火眼金睛", EyeFightItemHandler.self);
        handlers.put("火眼金睛·融合", EyeFightItemHandler.self);

        handlers.put("血玲珑", BloodLingLongHandler.self);
        handlers.put("血玲珑·融合", BloodLingLongHandler.self);
        handlers.put("中级血玲珑", BloodLingLongHandler.self);
        handlers.put("中级血玲珑·融合", BloodLingLongHandler.self);

        handlers.put("法玲珑", MagicLingLongHandler.self);
        handlers.put("法玲珑·融合", MagicLingLongHandler.self);
        handlers.put("中级法玲珑", MagicLingLongHandler.self);
        handlers.put("中级法玲珑·融合", MagicLingLongHandler.self);

        handlers.put("普通药品", MedicineHandler.self);
    }

}

/**
 * 火眼金睛
 */
class EyeFightItemHandler extends FightItemHandler {

    static EyeFightItemHandler self = new EyeFightItemHandler();

    @Override
    boolean checkCondition(Fight fight, FightObject attacker, RoleEquip item) {
        //  修改火眼PK时可用
//        if (fight.getType() == Const.fightType_PK) {
//            RespMsg respMsg = new RespMsg();
//            String msg = "#R火眼金睛无法对该目标使用#n。";
//            respMsg.setMsg(msg);
//            byte[] body = AsktaoUtil.getMessageBody(respMsg);
//            RespSyncMessage respSyncMessage = new RespSyncMessage();
//            respSyncMessage.setCode((short) 8165);
//            respSyncMessage.setMsg(body);
//            MessagePusher.pushMessage(attacker.getRole(), respSyncMessage);
//            return false;
//        }

        return true;
    }

    @Override
    Boolean doAction(Fight fight, FightObject attacker, RoleEquip item) {
        // 火眼显示气血包需要抓
        FiedValue minValue = item.getFields().get((short) 1).getField().get((short) 42);
        Role role = attacker.getRole();
        if (SpringUtils.getBean(AttrService.class).getValue(minValue.getValue()) <= 1) {
            SpringUtils.getEquipService().delEquipNum(role, item, 1);
        } else {
            IoSession session = attacker.getSession();
            minValue.setValue((int) minValue.getValue() - 1);
            ArrayList<RoleEquip> roleEquips = new ArrayList<>();
            roleEquips.add(item);
            RespFlyInfo respEquipInfo = SpringUtils.getEquipService().getEquipInfo(roleEquips);
            MessagePusher.pushMessage(session, respEquipInfo);
        }

        Role master = attacker.getRole();
        // 不管是宠物还是玩家，统一放在玩家
        FightObject masterActor = fight.queryFightObject(master.getRoleId());
        masterActor.setStatusScore(StatusConst.STATUS_EYE, fight.getRound() + 5);

        return Boolean.TRUE;
    }

    @Override
    void broadcast(Fight fight, FightObject attacker, RoleEquip item, Object params) {
        String msg = "你使用了#R" + item.getName() + "#n，长按对方形象可查看气血。";
        Role master = attacker.getRole();
        notify(master, msg);

        List<FightObject> list = new ArrayList<>();
        list.add(attacker);
        list.addAll(fight.getTargetSide(attacker.getId()));
        FightMessageService fightMessageService = SpringUtils.getFightMessageService();
        for (FightObject huoyanObject : list) {
            FightMessageUtil.sendFightPackage(fight, fightMessageService.useItem(attacker.getId(), huoyanObject.getId(), 6070));
        }

        FightMessageUtil.sendFightPackage(fight, fightMessageService.eyeInfo(list), attacker.isASide());
    }

}

/**
 * 血玲珑
 */
class BloodLingLongHandler extends FightItemHandler {

    static BloodLingLongHandler self = new BloodLingLongHandler();

    @Override
    Object doAction(Fight fight, FightObject attacker, RoleEquip item) {
        FightObject target = fight.queryFightObject(attacker.getTargetId());
        // 使用等级小于120级 每次 39000 加10%最大血量
        // 大于120级 50000 +20%最大血量
        int life = 0;
        if (target.getLevel() < 120) {
            life = (int) (39000 + target.getMaxLife() * 0.1);
        } else {
            life = (int) (50000 + target.getMaxLife() * 0.1);
        }
        if (life + target.getCurrLife() >= target.getMaxLife()) { // 加血循环次数不对 加血应该在外面
            life = target.getMaxLife() - target.getCurrLife();
        }
        life = SpringUtils.getEquipService().useLinglong(attacker.getSession(), item, (short) 6, life);

        return life;
    }

    @Override
    void broadcast(Fight fight, FightObject attacker, RoleEquip item, Object params) {
        int life = NumberUtil.intValue(params);
        String msg = "你使用了#R" + item.getName() + "#n恢复了#R" + life + "#n点气血。";
        notify(attacker.getRole(), msg);
        FightObject target = fight.queryFightObject(attacker.getTargetId());
        onAddLife(fight, attacker, target, life);
    }
}


/**
 * 法玲珑
 */
class MagicLingLongHandler extends FightItemHandler {

    static MagicLingLongHandler self = new MagicLingLongHandler();

    @Override
    Object doAction(Fight fight, FightObject attacker, RoleEquip item) {
        FightObject target = fight.queryFightObject(attacker.getTargetId());
        // 使用等级小于120级 每次 26000 加10%最大法力
        // 大于120级 36000 +20%最大法力
        int mana = 0;
        if (target.getLevel() < 120) {
            // 使用等级小于120级 每次 26000 加10%最大法力
            // 大于120级 36000 +20%最大法力
            mana = (int) (26000 + target.getMaxMana() * 0.1);
        } else {
            mana = (int) (36000 + target.getMaxMana() * 0.2);
        }
        mana = SpringUtils.getEquipService().useLinglong(attacker.getSession(), item, (short) 11, mana);
        if (mana + target.getCurrMana() >= target.getMaxMana()) { // 加血循环次数不对 加血应该在外面
            mana = target.getMaxMana() - target.getCurrMana();
            target.setCurrMana(target.getMaxMana());// 加上道具所加的气血
        } else {
            target.setCurrMana(target.getCurrMana() + mana);// 加上道具所加的气血
        }
        return mana;
    }

    @Override
    void broadcast(Fight fight, FightObject attacker, RoleEquip item, Object params) {
        int mana = NumberUtil.intValue(params);
        String msg = "你使用了#R" + item.getName() + "#n恢复了#R" + mana + "#n点法力。";
        notify(attacker.getRole(), msg);

        FightObject target = fight.queryFightObject(attacker.getTargetId());
        onAddMana(fight, attacker, target, mana);
    }
}

class MedicineHandler extends FightItemHandler {

    static MedicineHandler self = new MedicineHandler();

    @Override
    Pair<String, Integer> doAction(Fight fight, FightObject attacker, RoleEquip item) {
        Medicine medicine = ShopDataPool.getMedicineBy(item.getName());
        int effect = 0;
        FightObject target = fight.queryFightObject(attacker.getTargetId());

        if (medicine == null) {
            return null;
        }

        String useType = "";
        if (medicine.getRecover_mana() > 0) {// 加蓝的
            useType = "mana";
            effect = medicine.getRecover_mana();
            if (effect + target.getCurrMana() >= target.getMaxMana()) { // 加血循环次数不对 加血应该在外面
                effect = target.getMaxMana() - target.getCurrMana();
                target.setCurrMana(target.getMaxMana());// 加上道具所加的气血
            } else {
                target.setCurrMana(target.getCurrMana() + effect);// 加上道具所加的气血

            }

        } else if (medicine.getRecover_life() > 0) {// 加血的
            useType = "life";
            effect = medicine.getRecover_life();
        }
        SpringUtils.getEquipService().delEquipNum(attacker.getRole(), item, 1);
        return new Pair<>(useType, effect);
    }

    @Override
    void broadcast(Fight fight, FightObject attacker, RoleEquip item, Object params) {
        Pair<String, Integer> pair = (Pair<String, Integer>) params;
        String msg = "";
        switch (pair.getFirst()) {
            case "life":
                msg = "你使用了#R" + item.getName() + "#n恢复了#R" + pair.getSecond() + "#n点气血。";
                break;
            case "mana":
                msg = "你使用了#R" + item.getName() + "#n恢复了#R" + pair.getSecond() + "#n点法力。";
                break;
        }
        notify(attacker.getRole(), msg);

        FightObject target = fight.queryFightObject(attacker.getTargetId());
        if ("life".equals(pair.getFirst())) {
            onAddLife(fight, attacker, target, pair.getSecond());
        } else {
            onAddMana(fight, attacker, target, pair.getSecond());
        }
    }
}